Skip to content

Commit 87852ae

Browse files
committed
[MIPS]Optimize ((signext (xor (trunc X), imm)) to (xor (signext_inreg X, i32), imm)
The constant operand of the XOR is an i32, which makes the two operands being truncated to i32, and sign extended to i64 afterwards. Since both of the i32 operands are sign extended to i64 before performing the TRUNCATE operation, we just remove the unnecessary TRUNCATE and SIGN_EXTEND. Fix #99783
1 parent 6646b65 commit 87852ae

File tree

4 files changed

+316
-164
lines changed

4 files changed

+316
-164
lines changed

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
521521
setOperationAction(ISD::TRAP, MVT::Other, Legal);
522522

523523
setTargetDAGCombine({ISD::SDIVREM, ISD::UDIVREM, ISD::SELECT, ISD::AND,
524-
ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL});
524+
ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL,
525+
ISD::SIGN_EXTEND});
525526

526527
if (Subtarget.isGP64bit())
527528
setMaxAtomicSizeInBitsSupported(64);
@@ -1221,6 +1222,43 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
12211222
DAG.getConstant(SMSize, DL, MVT::i32));
12221223
}
12231224

1225+
static SDValue performSignExtendCombine(SDNode *N, SelectionDAG &DAG,
1226+
TargetLowering::DAGCombinerInfo &DCI,
1227+
const MipsSubtarget &Subtarget) {
1228+
if (DCI.Level != AfterLegalizeDAG || !Subtarget.isGP64bit()) {
1229+
return SDValue();
1230+
}
1231+
1232+
SDValue N0 = N->getOperand(0);
1233+
EVT VT = N->getValueType(0);
1234+
1235+
// Pattern match XOR.
1236+
// $dst = (sign_extend (xor (trunc $src, i32), imm), i64)
1237+
// => $dst = (xor (signext_inreg $src, i32), imm as i64)
1238+
if (N0.getOpcode() == ISD::XOR &&
1239+
N0.getOperand(0).getOpcode() == ISD::TRUNCATE &&
1240+
N0.getOperand(1).getOpcode() == ISD::Constant) {
1241+
SDValue TruncateSource = N0.getOperand(0).getOperand(0);
1242+
auto *ConstantOperand = dyn_cast<ConstantSDNode>(N0->getOperand(1));
1243+
1244+
// Remove the unnecessary truncate + signext, and perform the operation
1245+
// using the initial sign-extended i64 values, with the constant also sign
1246+
// extended to i64. Note: ConstImm is either passed as a 32-bit immediate to
1247+
// xori, or gets "assembled" to anoter register and a xor is emitted, if
1248+
// ConstImm can't fit in 32 bits.
1249+
if (VT == MVT::i64 && VT == TruncateSource.getValueType()) {
1250+
SDValue FirstOperand =
1251+
DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N0), VT, TruncateSource,
1252+
DAG.getValueType(MVT::i32));
1253+
APInt ConstImm(64, ConstantOperand->getSExtValue(), true);
1254+
return DAG.getNode(ISD::XOR, SDLoc(N0), VT, FirstOperand,
1255+
DAG.getConstant(ConstImm, SDLoc(N0), VT));
1256+
}
1257+
}
1258+
1259+
return SDValue();
1260+
}
1261+
12241262
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
12251263
const {
12261264
SelectionDAG &DAG = DCI.DAG;
@@ -1246,6 +1284,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
12461284
return performSHLCombine(N, DAG, DCI, Subtarget);
12471285
case ISD::SUB:
12481286
return performSUBCombine(N, DAG, DCI, Subtarget);
1287+
case ISD::SIGN_EXTEND:
1288+
return performSignExtendCombine(N, DAG, DCI, Subtarget);
12491289
}
12501290

12511291
return SDValue();

0 commit comments

Comments
 (0)