Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1912,14 +1912,36 @@ // compare). // Rotates are expensive instructions. If we're emitting a record-form - // rotate that can just be an andi, we should just emit the andi. - if ((MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) && - MI->getOperand(2).getImm() == 0) { + // rotate that can just be an andi/andis, we should just emit that. + if (MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) { + unsigned GPRRes = MI->getOperand(0).getReg(); + int64_t SH = MI->getOperand(2).getImm(); int64_t MB = MI->getOperand(3).getImm(); int64_t ME = MI->getOperand(4).getImm(); - if (MB < ME && MB >= 16) { - uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); - NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDIo : PPC::ANDIo8; + // We can only do this if both the start and end of the mask are in the + // same halfword. + bool MBInLoHWord = MB >= 16; + bool MEInLoHWord = ME >= 16; + uint64_t Mask = ~0LLU; + + if (MB <= ME && MBInLoHWord == MEInLoHWord && SH == 0) { + Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); + // The mask value needs to shift right 16 if we're emitting andis. + Mask >>= MBInLoHWord ? 0 : 16; + NewOpC = MIOpC == PPC::RLWINM ? + (MBInLoHWord ? PPC::ANDIo : PPC::ANDISo) : + (MBInLoHWord ? PPC::ANDIo8 :PPC::ANDISo8); + } else if (MRI->use_empty(GPRRes) && (ME == 31) && + (ME - MB + 1 == SH) && (MB >= 16)) { + // If we are rotating by the exact number of bits as are in the mask + // and the mask is in the least significant bits of the register, + // that's just an andis. (as long as the GPR result has no uses). + Mask = ((1LLU << 32) - 1) & ~((1LLU << (32 - SH)) - 1); + Mask >>= 16; + NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDISo :PPC::ANDISo8; + } + // If we've set the mask, we can transform. + if (Mask != ~0LLU) { MI->RemoveOperand(4); MI->RemoveOperand(3); MI->getOperand(2).setImm(Mask); Index: test/CodeGen/PowerPC/noPermuteFormasking.ll =================================================================== --- test/CodeGen/PowerPC/noPermuteFormasking.ll +++ test/CodeGen/PowerPC/noPermuteFormasking.ll @@ -40,3 +40,64 @@ exitBB: ; preds = %for.body.i.i.i.i.i.i.i.prol.loopexit ret void } + +define signext i32 @andis_bot(i32 signext %a, i32 signext %b) { +; CHECK-LABEL: andis_bot: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: andis. 5, 3, 1 +; CHECK-NEXT: li 5, 1 +; CHECK-NEXT: isel 4, 4, 5, 2 +; CHECK-NEXT: mullw 3, 4, 3 +; CHECK-NEXT: extsw 3, 3 +; CHECK-NEXT: blr +entry: + %and = and i32 %a, 65536 + %tobool = icmp eq i32 %and, 0 + %mul = select i1 %tobool, i32 %b, i32 1 + %cond = mul nsw i32 %mul, %a + ret i32 %cond +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @andis_mid(i32 signext %a, i32 signext %b) { +; CHECK-LABEL: andis_mid: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: andis. 5, 3, 252 +; CHECK-NEXT: li 5, 1 +; CHECK-NEXT: isel 4, 4, 5, 2 +; CHECK-NEXT: mullw 3, 4, 3 +; CHECK-NEXT: extsw 3, 3 +; CHECK-NEXT: blr +entry: + %and = and i32 %a, 16515072 + %tobool = icmp eq i32 %and, 0 + %mul = select i1 %tobool, i32 %b, i32 1 + %cond = mul nsw i32 %mul, %a + ret i32 %cond +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @andis_top(i32 signext %a, i32 signext %b) { +; CHECK-LABEL: andis_top: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: andis. 5, 3, 64512 +; CHECK-NEXT: li 5, 1 +; CHECK-NEXT: isel 4, 4, 5, 2 +; CHECK-NEXT: mullw 3, 4, 3 +; CHECK-NEXT: extsw 3, 3 +; CHECK-NEXT: blr +entry: + %tobool = icmp ugt i32 %a, 67108863 + %mul = select i1 %tobool, i32 1, i32 %b + %cond = mul nsw i32 %mul, %a + ret i32 %cond +} + +define i64 @andis_no_cmp(i64 %a, i64 %b) { +entry: + %and = and i64 %a, 65536 + %tobool = icmp eq i64 %and, 0 + %mul = select i1 %tobool, i64 %b, i64 1 + %cond = mul nsw i64 %mul, %a + ret i64 %cond +} Index: test/CodeGen/PowerPC/tail-dup-break-cfg.ll =================================================================== --- test/CodeGen/PowerPC/tail-dup-break-cfg.ll +++ test/CodeGen/PowerPC/tail-dup-break-cfg.ll @@ -15,12 +15,12 @@ ;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 1 ;CHECK-NEXT: bc 12, 1, [[BODY1LABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: # %test2 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: bne 0, [[BODY2LABEL:[._0-9A-Za-z]+]] ;CHECK: [[EXITLABEL:[._0-9A-Za-z]+]]: # %exit ;CHECK: blr ;CHECK-NEXT: [[BODY1LABEL]] -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: beq 0, [[EXITLABEL]] ;CHECK-NEXT: [[BODY2LABEL:[._0-9A-Za-z]+]]: ;CHECK: b [[EXITLABEL]] @@ -58,7 +58,7 @@ ;CHECK-NEXT: bc 4, 1, [[TEST2LABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: # %body1 ;CHECK: [[TEST2LABEL]]: # %test2 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: beq 0, [[EXITLABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: # %body2 ;CHECK: [[EXITLABEL:[._0-9A-Za-z]+]]: # %exit @@ -106,7 +106,7 @@ ; CHECK: # %succ ; CHECK: # %c ; CHECK: bl c -; CHECK: rlwinm. {{[0-9]+}}, {{[0-9]+}}, 0, 29, 29 +; CHECK: andi. {{[0-9]+}}, {{[0-9]+}}, 4 ; CHECK: beq ; CHECK: b define void @tail_dup_no_succ(i32 %tag) { Index: test/CodeGen/PowerPC/tail-dup-layout.ll =================================================================== --- test/CodeGen/PowerPC/tail-dup-layout.ll +++ test/CodeGen/PowerPC/tail-dup-layout.ll @@ -28,24 +28,24 @@ ;CHECK: andi. {{[0-9]+}}, [[TAGREG:[0-9]+]], 1 ;CHECK-NEXT: bc 12, 1, .[[OPT1LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: # %test2 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: bne 0, .[[OPT2LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: .[[TEST3LABEL:[_0-9A-Za-z]+]]: # %test3 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: bne 0, .[[OPT3LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: .[[TEST4LABEL:[_0-9A-Za-z]+]]: # %test4 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 28, 28 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 8 ;CHECK-NEXT: bne 0, .[[OPT4LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: .[[EXITLABEL:[_0-9A-Za-z]+]]: # %exit ;CHECK: blr ;CHECK-NEXT: .[[OPT1LABEL]]: -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: beq 0, .[[TEST3LABEL]] ;CHECK-NEXT: .[[OPT2LABEL]]: -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: beq 0, .[[TEST4LABEL]] ;CHECK-NEXT: .[[OPT3LABEL]]: -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 28, 28 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 8 ;CHECK-NEXT: beq 0, .[[EXITLABEL]] ;CHECK-NEXT: .[[OPT4LABEL]]: ;CHECK: b .[[EXITLABEL]] @@ -119,18 +119,18 @@ ;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 1 ;CHECK-NEXT: bc 12, 1, .[[OPT1LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: # %test2 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: bne 0, .[[OPT2LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: .[[TEST3LABEL:[_0-9A-Za-z]+]]: # %test3 -;CHECK-NEXT: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK-NEXT: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: bne 0, .[[OPT3LABEL:[_0-9A-Za-z]+]] ;CHECK-NEXT: .[[EXITLABEL:[_0-9A-Za-z]+]]: # %exit ;CHECK: blr ;CHECK-NEXT: .[[OPT1LABEL]]: -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: beq 0, .[[TEST3LABEL]] ;CHECK-NEXT: .[[OPT2LABEL]]: -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: beq 0, .[[EXITLABEL]] ;CHECK-NEXT: .[[OPT3LABEL]]: ;CHECK: b .[[EXITLABEL]] @@ -285,23 +285,23 @@ ;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 1 ;CHECK-NEXT: bc 12, 1, .[[OPT1LABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: # %test2 -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: bne 0, .[[OPT2LABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: .[[TEST3LABEL:[._0-9A-Za-z]+]]: # %test3 -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: bne 0, .[[OPT3LABEL:[._0-9A-Za-z]+]] ;CHECK-NEXT: .[[TEST4LABEL:[._0-9A-Za-z]+]]: # %{{(test4|optional3)}} -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 28, 28 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 8 ;CHECK-NEXT: beq 0, .[[LATCHLABEL]] ;CHECK-NEXT: b .[[OPT4LABEL:[._0-9A-Za-z]+]] ;CHECK: [[OPT1LABEL]] -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 30, 30 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 2 ;CHECK-NEXT: beq 0, .[[TEST3LABEL]] ;CHECK-NEXT: .[[OPT2LABEL]] -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 29, 29 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 4 ;CHECK-NEXT: beq 0, .[[TEST4LABEL]] ;CHECK-NEXT: .[[OPT3LABEL]] -;CHECK: rlwinm. {{[0-9]+}}, [[TAGREG]], 0, 28, 28 +;CHECK: andi. {{[0-9]+}}, [[TAGREG]], 8 ;CHECK-NEXT: beq 0, .[[LATCHLABEL]] ;CHECK: [[OPT4LABEL]]: ;CHECK: b .[[LATCHLABEL]] @@ -375,12 +375,12 @@ ; Make sure then2 falls through from test2 ; CHECK-NOT: # %{{[-_a-zA-Z0-9]+}} ; CHECK: # %bb.{{[0-9]+}}: # %then2 -; CHECK: rlwinm. {{[0-9]+}}, {{[0-9]+}}, 0, 29, 29 +; CHECK: andi. {{[0-9]+}}, {{[0-9]+}}, 4 ; CHECK: # %else1 ; CHECK: bl a ; CHECK: bl a ; Make sure then2 was copied into else1 -; CHECK: rlwinm. {{[0-9]+}}, {{[0-9]+}}, 0, 29, 29 +; CHECK: andi. {{[0-9]+}}, {{[0-9]+}}, 4 ; CHECK: # %end1 ; CHECK: bl d ; CHECK: # %else2