SDValue visitShiftByConstant(SDNode *N, ConstantSDNode *Amt);
SDValue foldSelectOfConstants(SDNode *N);
+ SDValue foldBinOpIntoSelect(SDNode *BO);
bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS);
SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N);
SDValue SimplifySelect(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2);
return Const != nullptr && !Const->isOpaque() ? Const : nullptr;
}
+SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
+ auto BinOpcode = BO->getOpcode();
+ assert((BinOpcode == ISD::ADD || BinOpcode == ISD::SUB ||
+ BinOpcode == ISD::MUL || BinOpcode == ISD::SDIV ||
+ BinOpcode == ISD::UDIV || BinOpcode == ISD::SREM ||
+ BinOpcode == ISD::UREM || BinOpcode == ISD::AND ||
+ BinOpcode == ISD::OR || BinOpcode == ISD::XOR ||
+ BinOpcode == ISD::SHL || BinOpcode == ISD::SRL ||
+ BinOpcode == ISD::SRA || BinOpcode == ISD::FADD ||
+ BinOpcode == ISD::FSUB || BinOpcode == ISD::FMUL ||
+ BinOpcode == ISD::FDIV || BinOpcode == ISD::FREM) &&
+ "Unexpected binary operator");
+
+ SDValue C1 = BO->getOperand(1);
+ if (!isConstantOrConstantVector(C1) &&
+ !isConstantFPBuildVectorOrConstantFP(C1))
+ return SDValue();
+
+ // Don't do this unless the old select is going away. We want to eliminate the
+ // binary operator, not replace a binop with a select.
+ // TODO: Handle ISD::SELECT_CC.
+ SDValue Sel = BO->getOperand(0);
+ if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse())
+ return SDValue();
+
+ SDValue CT = Sel.getOperand(1);
+ if (!isConstantOrConstantVector(CT) &&
+ !isConstantFPBuildVectorOrConstantFP(CT))
+ return SDValue();
+
+ SDValue CF = Sel.getOperand(2);
+ if (!isConstantOrConstantVector(CF) &&
+ !isConstantFPBuildVectorOrConstantFP(CF))
+ 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), C1 --> select Cond, CT + C1, CF + C1
+ EVT VT = Sel.getValueType();
+ SDLoc DL(Sel);
+ SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1);
+ assert((isConstantOrConstantVector(NewCT) ||
+ isConstantFPBuildVectorOrConstantFP(NewCT)) &&
+ "Failed to constant fold a binop with constant operands");
+
+ SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1);
+ assert((isConstantOrConstantVector(NewCF) ||
+ isConstantFPBuildVectorOrConstantFP(NewCF)) &&
+ "Failed to constant fold a binop with constant operands");
+
+ return DAG.getSelect(DL, VT, Sel.getOperand(0), NewCT, NewCF);
+}
+
SDValue DAGCombiner::visitADD(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
}
}
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// reassociate add
if (SDValue RADD = ReassociateOps(ISD::ADD, DL, N0, N1))
return RADD;
N1.getNode());
}
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
ConstantSDNode *N1C = getAsNonOpaqueConstant(N1);
// fold (sub x, c) -> (add x, -c)
// fold (mul x, 1) -> x
if (N1IsConst && ConstValue1 == 1 && IsFullSplat)
return N0;
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (mul x, -1) -> 0-x
if (N1IsConst && ConstValue1.isAllOnesValue()) {
SDLoc DL(N);
return DAG.getNode(ISD::SUB, DL, VT,
DAG.getConstant(0, DL, VT), N0);
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// If we know the sign bits of both operands are zero, strength reduce to a
// udiv instead. Handles (X&15) /s 4 -> X&15 >> 2
if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0))
N0C, N1C))
return Folded;
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (udiv x, (1 << c)) -> x >>u c
if (isConstantOrConstantVector(N1, /*NoOpaques*/ true) &&
DAG.isKnownToBeAPowerOfTwo(N1)) {
if (SDValue Folded = DAG.FoldConstantArithmetic(Opcode, DL, VT, N0C, N1C))
return Folded;
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
if (isSigned) {
// If we know the sign bits of both operands are zero, strength reduce to a
// urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15
if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0),
APInt::getAllOnesValue(BitWidth)))
return DAG.getConstant(0, SDLoc(N), VT);
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// reassociate and
if (SDValue RAND = ReassociateOps(ISD::AND, SDLoc(N), N0, N1))
return RAND;
// fold (or x, -1) -> -1
if (isAllOnesConstant(N1))
return N1;
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (or x, c) -> c iff (x & ~c) == 0
if (N1C && DAG.MaskedValueIsZero(N0, ~N1C->getAPIntValue()))
return N1;
// fold (xor x, 0) -> x
if (isNullConstant(N1))
return N0;
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// reassociate xor
if (SDValue RXOR = ReassociateOps(ISD::XOR, SDLoc(N), N0, N1))
return RXOR;
// fold (shl undef, x) -> 0
if (N0.isUndef())
return DAG.getConstant(0, SDLoc(N), VT);
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// if (shl x, c) is known to be zero, return 0
if (DAG.MaskedValueIsZero(SDValue(N, 0),
APInt::getAllOnesValue(OpSizeInBits)))
// fold (sra x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports
// sext_inreg.
if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) {
// fold (srl x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
+
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// if (srl x, c) is known to be zero, return 0
if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0),
APInt::getAllOnesValue(OpSizeInBits)))
if (N0CFP && !N1CFP)
return DAG.getNode(ISD::FADD, DL, VT, N1, N0, Flags);
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (fadd A, (fneg B)) -> (fsub A, B)
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
isNegatibleForFree(N1, LegalOperations, TLI, &Options) == 2)
if (N0CFP && N1CFP)
return DAG.getNode(ISD::FSUB, DL, VT, N0, N1, Flags);
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
// fold (fsub A, (fneg B)) -> (fadd A, B)
if (isNegatibleForFree(N1, LegalOperations, TLI, &Options))
return DAG.getNode(ISD::FADD, DL, VT, N0,
if (N1CFP && N1CFP->isExactlyValue(1.0))
return N0;
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
if (Options.UnsafeFPMath) {
// fold (fmul A, 0) -> 0
if (N1CFP && N1CFP->isZero())
if (N0CFP && N1CFP)
return DAG.getNode(ISD::FDIV, SDLoc(N), VT, N0, N1, Flags);
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
if (Options.UnsafeFPMath) {
// fold (fdiv X, c2) -> fmul X, 1/c2 if losing precision is acceptable.
if (N1CFP) {
return DAG.getNode(ISD::FREM, SDLoc(N), VT, N0, N1,
&cast<BinaryWithFlagsSDNode>(N)->Flags);
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
+ return NewSel;
+
return SDValue();
}
; ISEL-LABEL: sel_constants_add_constant:
; ISEL: # BB#0:
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
+; ISEL-NEXT: li 4, 1
+; ISEL-NEXT: li 3, 28
; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: addi 3, 3, 5
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_add_constant:
; NO_ISEL: # BB#0:
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
+; NO_ISEL-NEXT: li 4, 1
+; NO_ISEL-NEXT: li 3, 28
; NO_ISEL-NEXT: bc 12, 1, .LBB21_1
-; NO_ISEL-NEXT: b .LBB21_2
+; NO_ISEL-NEXT: blr
; NO_ISEL-NEXT: .LBB21_1:
; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB21_2:
-; NO_ISEL-NEXT: addi 3, 3, 5
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = add i8 %sel, 5
define i8 @sel_constants_sub_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_sub_constant:
; ISEL: # BB#0:
+; ISEL-NEXT: li 4, 0
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: addi 3, 3, -5
+; ISEL-NEXT: oris 3, 4, 65535
+; ISEL-NEXT: li 4, 18
+; ISEL-NEXT: ori 3, 3, 65527
+; ISEL-NEXT: isel 3, 3, 4, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_sub_constant:
; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: li 4, 0
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
-; NO_ISEL-NEXT: bc 12, 1, .LBB22_1
-; NO_ISEL-NEXT: b .LBB22_2
-; NO_ISEL-NEXT: .LBB22_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB22_2:
-; NO_ISEL-NEXT: addi 3, 3, -5
+; NO_ISEL-NEXT: oris 3, 4, 65535
+; NO_ISEL-NEXT: li 4, 18
+; NO_ISEL-NEXT: ori 3, 3, 65527
+; NO_ISEL-NEXT: bclr 12, 1, 0
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = sub i8 %sel, 5
define i8 @sel_constants_mul_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_mul_constant:
; ISEL: # BB#0:
+; ISEL-NEXT: lis 4, 16383
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: mulli 3, 3, 5
+; ISEL-NEXT: ori 3, 4, 65531
+; ISEL-NEXT: li 4, 115
+; ISEL-NEXT: sldi 3, 3, 2
+; ISEL-NEXT: isel 3, 3, 4, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_mul_constant:
; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: lis 4, 16383
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
-; NO_ISEL-NEXT: bc 12, 1, .LBB23_1
-; NO_ISEL-NEXT: b .LBB23_2
-; NO_ISEL-NEXT: .LBB23_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB23_2:
-; NO_ISEL-NEXT: mulli 3, 3, 5
+; NO_ISEL-NEXT: ori 3, 4, 65531
+; NO_ISEL-NEXT: li 4, 115
+; NO_ISEL-NEXT: sldi 3, 3, 2
+; NO_ISEL-NEXT: bclr 12, 1, 0
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = mul i8 %sel, 5
; ISEL-LABEL: sel_constants_sdiv_constant:
; ISEL: # BB#0:
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: lis 5, 26214
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
-; ISEL-NEXT: ori 12, 5, 26215
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: mulld 3, 3, 12
-; ISEL-NEXT: rldicl 4, 3, 1, 63
-; ISEL-NEXT: sradi 3, 3, 33
-; ISEL-NEXT: add 3, 3, 4
+; ISEL-NEXT: li 3, 4
+; ISEL-NEXT: isel 3, 0, 3, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_sdiv_constant:
; NO_ISEL: # BB#0:
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: lis 5, 26214
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
-; NO_ISEL-NEXT: ori 12, 5, 26215
+; NO_ISEL-NEXT: li 3, 4
; NO_ISEL-NEXT: bc 12, 1, .LBB24_1
-; NO_ISEL-NEXT: b .LBB24_2
+; NO_ISEL-NEXT: blr
; NO_ISEL-NEXT: .LBB24_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB24_2:
-; NO_ISEL-NEXT: mulld 3, 3, 12
-; NO_ISEL-NEXT: rldicl 4, 3, 1, 63
-; NO_ISEL-NEXT: sradi 3, 3, 33
-; NO_ISEL-NEXT: add 3, 3, 4
+; NO_ISEL-NEXT: addi 3, 0, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = sdiv i8 %sel, 5
define i8 @sel_constants_udiv_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_udiv_constant:
; ISEL: # BB#0:
-; ISEL-NEXT: lis 4, 16383
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 5, 0
-; ISEL-NEXT: ori 3, 4, 65535
-; ISEL-NEXT: li 4, 23
-; ISEL-NEXT: oris 12, 5, 52428
-; ISEL-NEXT: sldi 3, 3, 2
-; ISEL-NEXT: isel 3, 3, 4, 1
-; ISEL-NEXT: ori 4, 12, 52429
-; ISEL-NEXT: clrldi 3, 3, 56
-; ISEL-NEXT: mulld 3, 3, 4
-; ISEL-NEXT: rldicl 3, 3, 30, 34
+; ISEL-NEXT: li 4, 50
+; ISEL-NEXT: li 3, 4
+; ISEL-NEXT: isel 3, 4, 3, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_udiv_constant:
; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: lis 4, 16383
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 5, 0
-; NO_ISEL-NEXT: ori 3, 4, 65535
-; NO_ISEL-NEXT: li 4, 23
-; NO_ISEL-NEXT: oris 12, 5, 52428
-; NO_ISEL-NEXT: sldi 3, 3, 2
-; NO_ISEL-NEXT: bc 12, 1, .LBB25_2
-; NO_ISEL-NEXT: # BB#1:
-; NO_ISEL-NEXT: ori 3, 4, 0
-; NO_ISEL-NEXT: b .LBB25_2
-; NO_ISEL-NEXT: .LBB25_2:
-; NO_ISEL-NEXT: ori 4, 12, 52429
-; NO_ISEL-NEXT: clrldi 3, 3, 56
-; NO_ISEL-NEXT: mulld 3, 3, 4
-; NO_ISEL-NEXT: rldicl 3, 3, 30, 34
+; NO_ISEL-NEXT: li 4, 50
+; NO_ISEL-NEXT: li 3, 4
+; NO_ISEL-NEXT: bc 12, 1, .LBB25_1
+; NO_ISEL-NEXT: blr
+; NO_ISEL-NEXT: .LBB25_1:
+; NO_ISEL-NEXT: addi 3, 4, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = udiv i8 %sel, 5
define i8 @sel_constants_srem_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_srem_constant:
; ISEL: # BB#0:
+; ISEL-NEXT: lis 4, 16383
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: lis 12, 26214
-; ISEL-NEXT: li 3, 23
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: ori 4, 12, 26215
-; ISEL-NEXT: extsw 3, 3
-; ISEL-NEXT: mulld 4, 3, 4
-; ISEL-NEXT: rldicl 5, 4, 1, 63
-; ISEL-NEXT: sradi 4, 4, 33
-; ISEL-NEXT: add 4, 4, 5
-; ISEL-NEXT: mulli 4, 4, 5
-; ISEL-NEXT: subf 3, 4, 3
+; ISEL-NEXT: ori 3, 4, 65535
+; ISEL-NEXT: li 4, 3
+; ISEL-NEXT: sldi 3, 3, 2
+; ISEL-NEXT: isel 3, 3, 4, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_srem_constant:
; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: lis 4, 16383
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: lis 12, 26214
-; NO_ISEL-NEXT: li 3, 23
-; NO_ISEL-NEXT: bc 12, 1, .LBB26_1
-; NO_ISEL-NEXT: b .LBB26_2
-; NO_ISEL-NEXT: .LBB26_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB26_2:
-; NO_ISEL-NEXT: ori 4, 12, 26215
-; NO_ISEL-NEXT: extsw 3, 3
-; NO_ISEL-NEXT: mulld 4, 3, 4
-; NO_ISEL-NEXT: rldicl 5, 4, 1, 63
-; NO_ISEL-NEXT: sradi 4, 4, 33
-; NO_ISEL-NEXT: add 4, 4, 5
-; NO_ISEL-NEXT: mulli 4, 4, 5
-; NO_ISEL-NEXT: subf 3, 4, 3
+; NO_ISEL-NEXT: ori 3, 4, 65535
+; NO_ISEL-NEXT: li 4, 3
+; NO_ISEL-NEXT: sldi 3, 3, 2
+; NO_ISEL-NEXT: bclr 12, 1, 0
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = srem i8 %sel, 5
; ISEL-LABEL: sel_constants_urem_constant:
; ISEL: # BB#0:
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 12, 0
-; ISEL-NEXT: li 3, 23
+; ISEL-NEXT: li 4, 2
+; ISEL-NEXT: li 3, 3
; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: oris 4, 12, 52428
-; ISEL-NEXT: rlwinm 3, 3, 0, 24, 31
-; ISEL-NEXT: ori 4, 4, 52429
-; ISEL-NEXT: clrldi 5, 3, 32
-; ISEL-NEXT: mulld 4, 5, 4
-; ISEL-NEXT: rldicl 4, 4, 30, 34
-; ISEL-NEXT: mulli 4, 4, 5
-; ISEL-NEXT: subf 3, 4, 3
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_urem_constant:
; NO_ISEL: # BB#0:
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 12, 0
-; NO_ISEL-NEXT: li 3, 23
+; NO_ISEL-NEXT: li 4, 2
+; NO_ISEL-NEXT: li 3, 3
; NO_ISEL-NEXT: bc 12, 1, .LBB27_1
-; NO_ISEL-NEXT: b .LBB27_2
+; NO_ISEL-NEXT: blr
; NO_ISEL-NEXT: .LBB27_1:
; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB27_2:
-; NO_ISEL-NEXT: oris 4, 12, 52428
-; NO_ISEL-NEXT: rlwinm 3, 3, 0, 24, 31
-; NO_ISEL-NEXT: ori 4, 4, 52429
-; NO_ISEL-NEXT: clrldi 5, 3, 32
-; NO_ISEL-NEXT: mulld 4, 5, 4
-; NO_ISEL-NEXT: rldicl 4, 4, 30, 34
-; NO_ISEL-NEXT: mulli 4, 4, 5
-; NO_ISEL-NEXT: subf 3, 4, 3
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = urem i8 %sel, 5
define i8 @sel_constants_and_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_and_constant:
; ISEL: # BB#0:
-; ISEL-NEXT: lis 4, 16383
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: ori 3, 4, 65535
-; ISEL-NEXT: li 4, 23
-; ISEL-NEXT: sldi 3, 3, 2
-; ISEL-NEXT: isel 3, 3, 4, 1
-; ISEL-NEXT: andi. 3, 3, 5
+; ISEL-NEXT: li 4, 4
+; ISEL-NEXT: li 3, 5
+; ISEL-NEXT: isel 3, 4, 3, 1
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_and_constant:
; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: lis 4, 16383
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: ori 3, 4, 65535
-; NO_ISEL-NEXT: li 4, 23
-; NO_ISEL-NEXT: sldi 3, 3, 2
-; NO_ISEL-NEXT: bc 12, 1, .LBB28_2
-; NO_ISEL-NEXT: # BB#1:
-; NO_ISEL-NEXT: ori 3, 4, 0
-; NO_ISEL-NEXT: b .LBB28_2
-; NO_ISEL-NEXT: .LBB28_2:
-; NO_ISEL-NEXT: andi. 3, 3, 5
+; NO_ISEL-NEXT: li 4, 4
+; NO_ISEL-NEXT: li 3, 5
+; NO_ISEL-NEXT: bc 12, 1, .LBB28_1
+; NO_ISEL-NEXT: blr
+; NO_ISEL-NEXT: .LBB28_1:
+; NO_ISEL-NEXT: addi 3, 4, 0
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = and i8 %sel, 5
define i8 @sel_constants_or_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_or_constant:
; ISEL: # BB#0:
-; ISEL-NEXT: lis 4, 16383
+; ISEL-NEXT: li 4, 0
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: ori 3, 4, 65535
+; ISEL-NEXT: oris 3, 4, 65535
; ISEL-NEXT: li 4, 23
-; ISEL-NEXT: sldi 3, 3, 2
+; ISEL-NEXT: ori 3, 3, 65533
; ISEL-NEXT: isel 3, 3, 4, 1
-; ISEL-NEXT: ori 3, 3, 5
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_or_constant:
; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: lis 4, 16383
+; NO_ISEL-NEXT: li 4, 0
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: ori 3, 4, 65535
+; NO_ISEL-NEXT: oris 3, 4, 65535
; NO_ISEL-NEXT: li 4, 23
-; NO_ISEL-NEXT: sldi 3, 3, 2
-; NO_ISEL-NEXT: bc 12, 1, .LBB29_2
+; NO_ISEL-NEXT: ori 3, 3, 65533
+; NO_ISEL-NEXT: bclr 12, 1, 0
; NO_ISEL-NEXT: # BB#1:
; NO_ISEL-NEXT: ori 3, 4, 0
-; NO_ISEL-NEXT: b .LBB29_2
-; NO_ISEL-NEXT: .LBB29_2:
-; NO_ISEL-NEXT: ori 3, 3, 5
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = or i8 %sel, 5
define i8 @sel_constants_xor_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_xor_constant:
; ISEL: # BB#0:
-; ISEL-NEXT: lis 4, 16383
+; ISEL-NEXT: li 4, 0
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: ori 3, 4, 65535
-; ISEL-NEXT: li 4, 23
-; ISEL-NEXT: sldi 3, 3, 2
+; ISEL-NEXT: oris 3, 4, 65535
+; ISEL-NEXT: li 4, 18
+; ISEL-NEXT: ori 3, 3, 65529
; ISEL-NEXT: isel 3, 3, 4, 1
-; ISEL-NEXT: xori 3, 3, 5
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_xor_constant:
; NO_ISEL: # BB#0:
-; NO_ISEL-NEXT: lis 4, 16383
+; NO_ISEL-NEXT: li 4, 0
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: ori 3, 4, 65535
-; NO_ISEL-NEXT: li 4, 23
-; NO_ISEL-NEXT: sldi 3, 3, 2
-; NO_ISEL-NEXT: bc 12, 1, .LBB30_2
+; NO_ISEL-NEXT: oris 3, 4, 65535
+; NO_ISEL-NEXT: li 4, 18
+; NO_ISEL-NEXT: ori 3, 3, 65529
+; NO_ISEL-NEXT: bclr 12, 1, 0
; NO_ISEL-NEXT: # BB#1:
; NO_ISEL-NEXT: ori 3, 4, 0
-; NO_ISEL-NEXT: b .LBB30_2
-; NO_ISEL-NEXT: .LBB30_2:
-; NO_ISEL-NEXT: xori 3, 3, 5
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = xor i8 %sel, 5
define i8 @sel_constants_shl_constant(i1 %cond) {
; ISEL-LABEL: sel_constants_shl_constant:
; ISEL: # BB#0:
+; ISEL-NEXT: lis 5, 511
+; ISEL-NEXT: lis 4, 2047
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
+; ISEL-NEXT: ori 3, 4, 65535
+; ISEL-NEXT: ori 12, 5, 65535
+; ISEL-NEXT: sldi 3, 3, 5
+; ISEL-NEXT: sldi 4, 12, 7
; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: slwi 3, 3, 5
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_shl_constant:
; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: lis 5, 511
+; NO_ISEL-NEXT: lis 4, 2047
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
+; NO_ISEL-NEXT: ori 3, 4, 65535
+; NO_ISEL-NEXT: ori 12, 5, 65535
+; NO_ISEL-NEXT: sldi 3, 3, 5
+; NO_ISEL-NEXT: sldi 4, 12, 7
; NO_ISEL-NEXT: bc 12, 1, .LBB31_1
-; NO_ISEL-NEXT: b .LBB31_2
+; NO_ISEL-NEXT: blr
; NO_ISEL-NEXT: .LBB31_1:
; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB31_2:
-; NO_ISEL-NEXT: slwi 3, 3, 5
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = shl i8 %sel, 5
; ISEL-LABEL: sel_constants_lshr_constant:
; ISEL: # BB#0:
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
+; ISEL-NEXT: li 4, 7
+; ISEL-NEXT: li 3, 0
; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: rlwinm 3, 3, 27, 29, 31
; ISEL-NEXT: blr
;
; NO_ISEL-LABEL: sel_constants_lshr_constant:
; NO_ISEL: # BB#0:
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
+; NO_ISEL-NEXT: li 4, 7
+; NO_ISEL-NEXT: li 3, 0
; NO_ISEL-NEXT: bc 12, 1, .LBB32_1
-; NO_ISEL-NEXT: b .LBB32_2
+; NO_ISEL-NEXT: blr
; NO_ISEL-NEXT: .LBB32_1:
; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB32_2:
-; NO_ISEL-NEXT: rlwinm 3, 3, 27, 29, 31
; NO_ISEL-NEXT: blr
%sel = select i1 %cond, i8 -4, i8 23
%bo = lshr i8 %sel, 5
}
define i8 @sel_constants_ashr_constant(i1 %cond) {
-; ISEL-LABEL: sel_constants_ashr_constant:
+; ALL-LABEL: sel_constants_ashr_constant:
+; ALL: # BB#0:
+; ALL-NEXT: clrldi 3, 3, 63
+; ALL-NEXT: neg 3, 3
+; ALL-NEXT: blr
+ %sel = select i1 %cond, i8 -4, i8 23
+ %bo = ashr i8 %sel, 5
+ ret i8 %bo
+}
+
+define double @sel_constants_fadd_constant(i1 %cond) {
+; ISEL-LABEL: sel_constants_fadd_constant:
; ISEL: # BB#0:
; ISEL-NEXT: andi. 3, 3, 1
-; ISEL-NEXT: li 4, -4
-; ISEL-NEXT: li 3, 23
-; ISEL-NEXT: isel 3, 4, 3, 1
-; ISEL-NEXT: srawi 3, 3, 5
+; ISEL-NEXT: addis 4, 2, .LCPI34_0@toc@ha
+; ISEL-NEXT: addis 3, 2, .LCPI34_1@toc@ha
+; ISEL-NEXT: addi 4, 4, .LCPI34_0@toc@l
+; ISEL-NEXT: addi 3, 3, .LCPI34_1@toc@l
+; ISEL-NEXT: isel 3, 3, 4, 1
+; ISEL-NEXT: lxsdx 1, 0, 3
; ISEL-NEXT: blr
;
-; NO_ISEL-LABEL: sel_constants_ashr_constant:
+; NO_ISEL-LABEL: sel_constants_fadd_constant:
; NO_ISEL: # BB#0:
; NO_ISEL-NEXT: andi. 3, 3, 1
-; NO_ISEL-NEXT: li 4, -4
-; NO_ISEL-NEXT: li 3, 23
-; NO_ISEL-NEXT: bc 12, 1, .LBB33_1
-; NO_ISEL-NEXT: b .LBB33_2
-; NO_ISEL-NEXT: .LBB33_1:
-; NO_ISEL-NEXT: addi 3, 4, 0
-; NO_ISEL-NEXT: .LBB33_2:
-; NO_ISEL-NEXT: srawi 3, 3, 5
+; NO_ISEL-NEXT: addis 4, 2, .LCPI34_0@toc@ha
+; NO_ISEL-NEXT: addis 3, 2, .LCPI34_1@toc@ha
+; NO_ISEL-NEXT: addi 4, 4, .LCPI34_0@toc@l
+; NO_ISEL-NEXT: addi 3, 3, .LCPI34_1@toc@l
+; NO_ISEL-NEXT: bc 12, 1, .LBB34_2
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
+; NO_ISEL-NEXT: b .LBB34_2
+; NO_ISEL-NEXT: .LBB34_2:
+; NO_ISEL-NEXT: lxsdx 1, 0, 3
; NO_ISEL-NEXT: blr
- %sel = select i1 %cond, i8 -4, i8 23
- %bo = ashr i8 %sel, 5
- ret i8 %bo
-}
-
-define double @sel_constants_fadd_constant(i1 %cond) {
-; ALL-LABEL: sel_constants_fadd_constant:
-; ALL: # BB#0:
-; ALL-NEXT: andi. 3, 3, 1
-; ALL-NEXT: bc 12, 1, .LBB34_2
-; ALL-NEXT: # BB#1:
-; ALL-NEXT: addis 3, 2, .LCPI34_0@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI34_0@toc@l
-; ALL-NEXT: lxsdx 0, 0, 3
-; ALL-NEXT: b .LBB34_3
-; ALL-NEXT: .LBB34_2:
-; ALL-NEXT: addis 3, 2, .LCPI34_1@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI34_1@toc@l
-; ALL-NEXT: lxsspx 0, 0, 3
-; ALL-NEXT: .LBB34_3:
-; ALL-NEXT: addis 3, 2, .LCPI34_2@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI34_2@toc@l
-; ALL-NEXT: lxsdx 1, 0, 3
-; ALL-NEXT: xsadddp 1, 0, 1
-; ALL-NEXT: blr
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fadd double %sel, 5.1
ret double %bo
}
define double @sel_constants_fsub_constant(i1 %cond) {
-; ALL-LABEL: sel_constants_fsub_constant:
-; ALL: # BB#0:
-; ALL-NEXT: andi. 3, 3, 1
-; ALL-NEXT: bc 12, 1, .LBB35_2
-; ALL-NEXT: # BB#1:
-; ALL-NEXT: addis 3, 2, .LCPI35_0@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI35_0@toc@l
-; ALL-NEXT: lxsdx 0, 0, 3
-; ALL-NEXT: b .LBB35_3
-; ALL-NEXT: .LBB35_2:
-; ALL-NEXT: addis 3, 2, .LCPI35_1@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI35_1@toc@l
-; ALL-NEXT: lxsspx 0, 0, 3
-; ALL-NEXT: .LBB35_3:
-; ALL-NEXT: addis 3, 2, .LCPI35_2@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI35_2@toc@l
-; ALL-NEXT: lxsdx 1, 0, 3
-; ALL-NEXT: xsadddp 1, 0, 1
-; ALL-NEXT: blr
+; ISEL-LABEL: sel_constants_fsub_constant:
+; ISEL: # BB#0:
+; ISEL-NEXT: andi. 3, 3, 1
+; ISEL-NEXT: addis 4, 2, .LCPI35_0@toc@ha
+; ISEL-NEXT: addis 3, 2, .LCPI35_1@toc@ha
+; ISEL-NEXT: addi 4, 4, .LCPI35_0@toc@l
+; ISEL-NEXT: addi 3, 3, .LCPI35_1@toc@l
+; ISEL-NEXT: isel 3, 3, 4, 1
+; ISEL-NEXT: lxsdx 1, 0, 3
+; ISEL-NEXT: blr
+;
+; NO_ISEL-LABEL: sel_constants_fsub_constant:
+; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: andi. 3, 3, 1
+; NO_ISEL-NEXT: addis 4, 2, .LCPI35_0@toc@ha
+; NO_ISEL-NEXT: addis 3, 2, .LCPI35_1@toc@ha
+; NO_ISEL-NEXT: addi 4, 4, .LCPI35_0@toc@l
+; NO_ISEL-NEXT: addi 3, 3, .LCPI35_1@toc@l
+; NO_ISEL-NEXT: bc 12, 1, .LBB35_2
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
+; NO_ISEL-NEXT: b .LBB35_2
+; NO_ISEL-NEXT: .LBB35_2:
+; NO_ISEL-NEXT: lxsdx 1, 0, 3
+; NO_ISEL-NEXT: blr
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fsub double %sel, 5.1
ret double %bo
}
define double @sel_constants_fmul_constant(i1 %cond) {
-; ALL-LABEL: sel_constants_fmul_constant:
-; ALL: # BB#0:
-; ALL-NEXT: andi. 3, 3, 1
-; ALL-NEXT: bc 12, 1, .LBB36_2
-; ALL-NEXT: # BB#1:
-; ALL-NEXT: addis 3, 2, .LCPI36_0@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI36_0@toc@l
-; ALL-NEXT: lxsdx 0, 0, 3
-; ALL-NEXT: b .LBB36_3
-; ALL-NEXT: .LBB36_2:
-; ALL-NEXT: addis 3, 2, .LCPI36_1@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI36_1@toc@l
-; ALL-NEXT: lxsspx 0, 0, 3
-; ALL-NEXT: .LBB36_3:
-; ALL-NEXT: addis 3, 2, .LCPI36_2@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI36_2@toc@l
-; ALL-NEXT: lxsdx 1, 0, 3
-; ALL-NEXT: xsmuldp 1, 0, 1
-; ALL-NEXT: blr
+; ISEL-LABEL: sel_constants_fmul_constant:
+; ISEL: # BB#0:
+; ISEL-NEXT: andi. 3, 3, 1
+; ISEL-NEXT: addis 4, 2, .LCPI36_0@toc@ha
+; ISEL-NEXT: addis 3, 2, .LCPI36_1@toc@ha
+; ISEL-NEXT: addi 4, 4, .LCPI36_0@toc@l
+; ISEL-NEXT: addi 3, 3, .LCPI36_1@toc@l
+; ISEL-NEXT: isel 3, 3, 4, 1
+; ISEL-NEXT: lxsdx 1, 0, 3
+; ISEL-NEXT: blr
+;
+; NO_ISEL-LABEL: sel_constants_fmul_constant:
+; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: andi. 3, 3, 1
+; NO_ISEL-NEXT: addis 4, 2, .LCPI36_0@toc@ha
+; NO_ISEL-NEXT: addis 3, 2, .LCPI36_1@toc@ha
+; NO_ISEL-NEXT: addi 4, 4, .LCPI36_0@toc@l
+; NO_ISEL-NEXT: addi 3, 3, .LCPI36_1@toc@l
+; NO_ISEL-NEXT: bc 12, 1, .LBB36_2
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
+; NO_ISEL-NEXT: b .LBB36_2
+; NO_ISEL-NEXT: .LBB36_2:
+; NO_ISEL-NEXT: lxsdx 1, 0, 3
+; NO_ISEL-NEXT: blr
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fmul double %sel, 5.1
ret double %bo
}
define double @sel_constants_fdiv_constant(i1 %cond) {
-; ALL-LABEL: sel_constants_fdiv_constant:
-; ALL: # BB#0:
-; ALL-NEXT: andi. 3, 3, 1
-; ALL-NEXT: bc 12, 1, .LBB37_2
-; ALL-NEXT: # BB#1:
-; ALL-NEXT: addis 3, 2, .LCPI37_0@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI37_0@toc@l
-; ALL-NEXT: lxsdx 0, 0, 3
-; ALL-NEXT: b .LBB37_3
-; ALL-NEXT: .LBB37_2:
-; ALL-NEXT: addis 3, 2, .LCPI37_1@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI37_1@toc@l
-; ALL-NEXT: lxsspx 0, 0, 3
-; ALL-NEXT: .LBB37_3:
-; ALL-NEXT: addis 3, 2, .LCPI37_2@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI37_2@toc@l
-; ALL-NEXT: lxsdx 1, 0, 3
-; ALL-NEXT: xsdivdp 1, 0, 1
-; ALL-NEXT: blr
+; ISEL-LABEL: sel_constants_fdiv_constant:
+; ISEL: # BB#0:
+; ISEL-NEXT: andi. 3, 3, 1
+; ISEL-NEXT: addis 4, 2, .LCPI37_0@toc@ha
+; ISEL-NEXT: addis 3, 2, .LCPI37_1@toc@ha
+; ISEL-NEXT: addi 4, 4, .LCPI37_0@toc@l
+; ISEL-NEXT: addi 3, 3, .LCPI37_1@toc@l
+; ISEL-NEXT: isel 3, 3, 4, 1
+; ISEL-NEXT: lxsdx 1, 0, 3
+; ISEL-NEXT: blr
+;
+; NO_ISEL-LABEL: sel_constants_fdiv_constant:
+; NO_ISEL: # BB#0:
+; NO_ISEL-NEXT: andi. 3, 3, 1
+; NO_ISEL-NEXT: addis 4, 2, .LCPI37_0@toc@ha
+; NO_ISEL-NEXT: addis 3, 2, .LCPI37_1@toc@ha
+; NO_ISEL-NEXT: addi 4, 4, .LCPI37_0@toc@l
+; NO_ISEL-NEXT: addi 3, 3, .LCPI37_1@toc@l
+; NO_ISEL-NEXT: bc 12, 1, .LBB37_2
+; NO_ISEL-NEXT: # BB#1:
+; NO_ISEL-NEXT: ori 3, 4, 0
+; NO_ISEL-NEXT: b .LBB37_2
+; NO_ISEL-NEXT: .LBB37_2:
+; NO_ISEL-NEXT: lxsdx 1, 0, 3
+; NO_ISEL-NEXT: blr
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fdiv double %sel, 5.1
ret double %bo
; ALL-NEXT: addis 3, 2, .LCPI38_0@toc@ha
; ALL-NEXT: addi 3, 3, .LCPI38_0@toc@l
; ALL-NEXT: lxsdx 1, 0, 3
-; ALL-NEXT: b .LBB38_3
+; ALL-NEXT: blr
; ALL-NEXT: .LBB38_2:
; ALL-NEXT: addis 3, 2, .LCPI38_1@toc@ha
; ALL-NEXT: addi 3, 3, .LCPI38_1@toc@l
; ALL-NEXT: lxsspx 1, 0, 3
-; ALL-NEXT: .LBB38_3:
-; ALL-NEXT: mflr 0
-; ALL-NEXT: std 0, 16(1)
-; ALL-NEXT: stdu 1, -96(1)
-; ALL-NEXT: .Lcfi0:
-; ALL-NEXT: .cfi_def_cfa_offset 96
-; ALL-NEXT: .Lcfi1:
-; ALL-NEXT: .cfi_offset lr, 16
-; ALL-NEXT: addis 3, 2, .LCPI38_2@toc@ha
-; ALL-NEXT: addi 3, 3, .LCPI38_2@toc@l
-; ALL-NEXT: lxsdx 2, 0, 3
-; ALL-NEXT: bl fmod
-; ALL-NEXT: nop
-; ALL-NEXT: addi 1, 1, 96
-; ALL-NEXT: ld 0, 16(1)
-; ALL-NEXT: mtlr 0
; ALL-NEXT: blr
%sel = select i1 %cond, double -4.0, double 23.3
%bo = frem double %sel, 5.1