Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -1006,20 +1006,14 @@ // MicroMips arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// -def : MipsPat<(i32 immLi16:$imm), - (LI16_MM immLi16:$imm)>; - -let AdditionalPredicates = [InMicroMips] in -defm : MaterializeImms; - -let Predicates = [InMicroMips] in { +let AdditionalPredicates = [InMicroMips] in { def : MipsPat<(i32 immLi16:$imm), (LI16_MM immLi16:$imm)>; - def : MipsPat<(i32 immSExt16:$imm), - (ADDiu_MM ZERO, immSExt16:$imm)>; - def : MipsPat<(i32 immZExt16:$imm), - (ORi_MM ZERO, immZExt16:$imm)>; + defm : MaterializeImms; +} + +let Predicates = [InMicroMips] in { def : MipsPat<(not GPRMM16:$in), (NOT16_MM GPRMM16:$in)>; def : MipsPat<(not GPR32:$in), Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1833,6 +1833,23 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; +def ORiPred : PatLeaf<(imm), [{ + uint64_t ZVal = N->getZExtValue(); + int64_t SVal = N->getSExtValue(); + bool cond = isUInt<16>(ZVal) && !isInt<16>(SVal); + return (uint32_t)ZVal == (unsigned short)ZVal && cond; +}], LO16>; + +def LUiPred : PatLeaf<(imm), [{ + int64_t Val = N->getSExtValue(); + return !isInt<16>(Val) && isInt<32>(Val) && !(Val & 0xffff); +}]>; + +def LUiORiPred : PatLeaf<(imm), [{ + int64_t SVal = N->getSExtValue(); + return isInt<32>(SVal) && (SVal & 0xffff); +}]>; + //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -2716,15 +2733,20 @@ Instruction ADDiuOp, Instruction LUiOp, Instruction ORiOp> { -// Small immediates -def : MipsPat<(VT immSExt16:$imm), (ADDiuOp ZEROReg, imm:$imm)>; -def : MipsPat<(VT immZExt16:$imm), (ORiOp ZEROReg, imm:$imm)>; +// Constant synthesis previously relied on the ordering of the patterns below. +// By making the predicates they use non-overlapping, the patterns were +// reordered so that the effect of the newly introduced predicates can be +// observed. + +// Arbitrary immediates +def : MipsPat<(VT LUiORiPred:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>; // Bits 32-16 set, sign/zero extended. -def : MipsPat<(VT immSExt32Low16Zero:$imm), (LUiOp (HI16 imm:$imm))>; +def : MipsPat<(VT LUiPred:$imm), (LUiOp (HI16 imm:$imm))>; -// Arbitrary immediates -def : MipsPat<(VT immSExt32:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>; +// Small immediates +def : MipsPat<(VT ORiPred:$imm), (ORiOp ZEROReg, imm:$imm)>; +def : MipsPat<(VT immSExt16:$imm), (ADDiuOp ZEROReg, imm:$imm)>; } let AdditionalPredicates = [NotInMicroMips] in Index: test/CodeGen/Mips/constMaterialization.ll =================================================================== --- test/CodeGen/Mips/constMaterialization.ll +++ test/CodeGen/Mips/constMaterialization.ll @@ -0,0 +1,123 @@ +; RUN: llc -march=mips < %s | FileCheck %s -check-prefixes=ALL,MIPS +; RUN: llc -march=mips < %s -mattr=+micromips | FileCheck %s -check-prefixes=ALL,MM + +; Constants generated using li16 +define i32 @Li16LowBoundary() { +entry: +; ALL-LABEL: Li16LowBoundary: + ; MIPS: addiu $2, $zero, -1 + ; MM: li16 $2, -1 + ; ALL-NOT: lui + ; ALL-NOT: ori + ; MIPS-NOT: li16 + ; MM-NOT: addiu + + ret i32 -1 +} + +define i32 @Li16HighBoundary() { +entry: +; ALL-LABEL: Li16HighBoundary: + ; MIPS: addiu $2, $zero, 126 + ; MM: li16 $2, 126 + ; ALL-NOT: lui + ; ALL-NOT: ori + ; MM-NOT: addiu + ; MIPS-NOT: li16 + + ret i32 126 +} + +; Constants generated using addiu +define i32 @AddiuLowBoundary() { +entry: +; ALL-LABEL: AddiuLowBoundary: + ; MIPS: addiu $2, $zero, -32768 + ; ALL-NOT: lui + ; ALL-NOT: ori + ; ALL-NOT: li16 + + ret i32 -32768 +} + +define i32 @AddiuZero() { +entry: +; ALL-LABEL: AddiuZero: + ; MIPS: addiu $2, $zero, 0 + ; MM: li16 $2, 0 + ; ALL-NOT: lui + ; ALL-NOT: ori + ; MIPS-NOT: li16 + ; MM-NOT: addiu + + ret i32 0 +} + +define i32 @AddiuHighBoundary() { +entry: +; ALL-LABEL: AddiuHighBoundary: + ; ALL: addiu $2, $zero, 32767 + ; ALL-NOT: lui + ; ALL-NOT: ori + ; ALL-NOT: li16 + + ret i32 32767 +} + +; Constants generated using ori +define i32 @OriLowBoundary() { +entry: +; ALL-LABEL: OriLowBoundary: + ; ALL: ori $2, $zero, 32768 + ; ALL-NOT: addiu + ; ALL-NOT: lui + ; ALL-NOT: li16 + + ret i32 32768 +} + +define i32 @OriHighBoundary() { +entry: +; ALL-LABEL: OriHighBoundary: + ; ALL: ori $2, $zero, 65535 + ; ALL-NOT: addiu + ; ALL-NOT: lui + ; ALL-NOT: li16 + + ret i32 65535 +} + +; Constants generated using lui +define i32 @Lui() { +entry: +; ALL-LABEL: Lui: + ; ALL: lui $2, 1 + ; ALL-NOT: addiu + ; ALL-NOT: ori + ; ALL-NOT: li16 + + ret i32 65536 +} + +; Constants generated using a combination of lui and ori +define i32 @LuiWithLowBitsSet() { +entry: +; ALL-LABEL: LuiWithLowBitsSet: + ; ALL: lui $1, 1 + ; ALL: ori $2, $1, 1 + ; ALL-NOT: addiu + ; ALL-NOT: li16 + + ret i32 65537 +} + +define i32 @BelowAddiuLowBoundary() { +entry: +; ALL-LABEL: BelowAddiuLowBoundary: + ; ALL: lui $1, 65535 + ; ALL: ori $2, $1, 32767 + ; ALL-NOT: addiu + ; ALL-NOT: li16 + + ret i32 -32769 +}