auto getI32Imm = [CurDAG, dl](unsigned Imm) {
return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
};
+
+ uint32_t Hi16OfLo32 = (Lo_32(Imm) >> 16) & 0xffff;
+ uint32_t Lo16OfLo32 = Lo_32(Imm) & 0xffff;
+
+ // Try to use 4 instructions to materialize the immediate which is "almost" a
+ // splat of a 32 bit immediate.
+ if (Hi16OfLo32 && Lo16OfLo32) {
+ uint32_t Hi16OfHi32 = (Hi_32(Imm) >> 16) & 0xffff;
+ uint32_t Lo16OfHi32 = Hi_32(Imm) & 0xffff;
+ bool IsSelected = false;
+
+ auto getSplat = [CurDAG, dl, getI32Imm](uint32_t Hi16, uint32_t Lo16) {
+ SDNode *Result =
+ CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(Hi16));
+ Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
+ SDValue(Result, 0), getI32Imm(Lo16));
+ SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
+ getI32Imm(0)};
+ return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
+ };
+
+ if (Hi16OfHi32 == Lo16OfHi32 && Lo16OfHi32 == Lo16OfLo32) {
+ IsSelected = true;
+ Result = getSplat(Hi16OfLo32, Lo16OfLo32);
+ // Modify Hi16OfHi32.
+ SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(48),
+ getI32Imm(0)};
+ Result = CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
+ } else if (Hi16OfHi32 == Hi16OfLo32 && Hi16OfLo32 == Lo16OfLo32) {
+ IsSelected = true;
+ Result = getSplat(Hi16OfHi32, Lo16OfHi32);
+ // Modify Lo16OfLo32.
+ SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(16),
+ getI32Imm(16), getI32Imm(31)};
+ Result = CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64, Ops);
+ } else if (Lo16OfHi32 == Lo16OfLo32 && Hi16OfLo32 == Lo16OfLo32) {
+ IsSelected = true;
+ Result = getSplat(Hi16OfHi32, Lo16OfHi32);
+ // Modify Hi16OfLo32.
+ SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(16),
+ getI32Imm(0), getI32Imm(15)};
+ Result = CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64, Ops);
+ }
+ if (IsSelected == true) {
+ if (InstCnt)
+ *InstCnt = 4;
+ return Result;
+ }
+ }
+
// Handle the upper 32 bit value.
Result =
selectI64ImmDirect(CurDAG, dl, Imm & 0xffffffff00000000, InstCntDirect);
// Add in the last bits as required.
- if (uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff) {
+ if (Hi16OfLo32) {
Result = CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64,
- SDValue(Result, 0), getI32Imm(Hi16));
+ SDValue(Result, 0), getI32Imm(Hi16OfLo32));
++InstCntDirect;
}
- if (uint32_t Lo16 = Lo_32(Imm) & 0xffff) {
+ if (Lo16OfLo32) {
Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
- getI32Imm(Lo16));
+ getI32Imm(Lo16OfLo32));
++InstCntDirect;
}
if (InstCnt)
define i64 @imm20() {
; CHECK-LABEL: imm20:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: lis 3, -13057
-; CHECK-NEXT: ori 3, 3, 52479
-; CHECK-NEXT: rldic 3, 3, 32, 0
-; CHECK-NEXT: oris 3, 3, 291
+; CHECK-NEXT: lis 3, 291
; CHECK-NEXT: ori 3, 3, 52479
+; CHECK-NEXT: rldimi 3, 3, 32, 0
+; CHECK-NEXT: rldimi 3, 3, 48, 0
; CHECK-NEXT: blr
entry:
ret i64 14771750698406366463 ;0xCCFFCCFF0123CCFF
}
+define i64 @imm21() {
+; CHECK-LABEL: imm21:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis 3, -13057
+; CHECK-NEXT: ori 3, 3, 291
+; CHECK-NEXT: rldimi 3, 3, 32, 0
+; CHECK-NEXT: rlwimi 3, 3, 16, 16, 31
+; CHECK-NEXT: blr
+entry:
+ ret i64 14771526556073315583 ;0xCCFF0123CCFFCCFF
+}
+
+define i64 @imm22() {
+; CHECK-LABEL: imm22:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis 3, 291
+; CHECK-NEXT: ori 3, 3, 52479
+; CHECK-NEXT: rldimi 3, 3, 32, 0
+; CHECK-NEXT: rlwimi 3, 3, 16, 0, 15
+; CHECK-NEXT: blr
+entry:
+ ret i64 82134617250843903 ;0x0123CCFFCCFFCCFF
+}
+
attributes #0 = { nounwind readnone }