@@ -123,9 +123,10 @@ class IRPromoter {
123
123
SmallPtrSetImpl<Value*> *Sources;
124
124
SmallPtrSetImpl<Instruction*> *Sinks;
125
125
SmallPtrSetImpl<Instruction*> *SafeToPromote;
126
+ SmallPtrSetImpl<Instruction*> *SafeWrap;
126
127
127
128
void ReplaceAllUsersOfWith (Value *From, Value *To);
128
- void PrepareConstants (void );
129
+ void PrepareWrappingAdds (void );
129
130
void ExtendSources (void );
130
131
void ConvertTruncs (void );
131
132
void PromoteTree (void );
@@ -141,16 +142,18 @@ class IRPromoter {
141
142
SetVector<Value*> &Visited,
142
143
SmallPtrSetImpl<Value*> &Sources,
143
144
SmallPtrSetImpl<Instruction*> &Sinks,
144
- SmallPtrSetImpl<Instruction*> &SafeToPromote);
145
+ SmallPtrSetImpl<Instruction*> &SafeToPromote,
146
+ SmallPtrSetImpl<Instruction*> &SafeWrap);
145
147
};
146
148
147
149
class ARMCodeGenPrepare : public FunctionPass {
148
150
const ARMSubtarget *ST = nullptr ;
149
151
IRPromoter *Promoter = nullptr ;
150
152
std::set<Value*> AllVisited;
151
153
SmallPtrSet<Instruction*, 8 > SafeToPromote;
154
+ SmallPtrSet<Instruction*, 4 > SafeWrap;
152
155
153
- bool isSafeOverflow (Instruction *I);
156
+ bool isSafeWrap (Instruction *I);
154
157
bool isSupportedValue (Value *V);
155
158
bool isLegalToPromote (Value *V);
156
159
bool TryToPromote (Value *V);
@@ -278,19 +281,14 @@ static bool isSink(Value *V) {
278
281
return isa<CallInst>(V);
279
282
}
280
283
281
- // / Return whether the instruction can be promoted within any modifications to
282
- // / its operands or result.
283
- bool ARMCodeGenPrepare::isSafeOverflow (Instruction *I) {
284
- // FIXME Do we need NSW too?
285
- if (isa<OverflowingBinaryOperator>(I) && I->hasNoUnsignedWrap ())
286
- return true ;
287
-
288
- // We can support a, potentially, overflowing instruction (I) if:
284
+ // / Return whether this instruction can safely wrap.
285
+ bool ARMCodeGenPrepare::isSafeWrap (Instruction *I) {
286
+ // We can support a, potentially, wrapping instruction (I) if:
289
287
// - It is only used by an unsigned icmp.
290
288
// - The icmp uses a constant.
291
- // - The overflowing value (I) is decreasing, i.e would underflow - wrapping
289
+ // - The wrapping value (I) is decreasing, i.e would underflow - wrapping
292
290
// around zero to become a larger number than before.
293
- // - The underflowing instruction (I) also uses a constant.
291
+ // - The wrapping instruction (I) also uses a constant.
294
292
//
295
293
// We can then use the two constants to calculate whether the result would
296
294
// wrap in respect to itself in the original bitwidth. If it doesn't wrap,
@@ -392,6 +390,7 @@ bool ARMCodeGenPrepare::isSafeOverflow(Instruction *I) {
392
390
return false ;
393
391
394
392
LLVM_DEBUG (dbgs () << " ARM CGP: Allowing safe overflow for " << *I << " \n " );
393
+ SafeWrap.insert (I);
395
394
return true ;
396
395
}
397
396
@@ -415,13 +414,16 @@ static bool shouldPromote(Value *V) {
415
414
// / Return whether we can safely mutate V's type to ExtTy without having to be
416
415
// / concerned with zero extending or truncation.
417
416
static bool isPromotedResultSafe (Value *V) {
417
+ if (GenerateSignBits (V))
418
+ return false ;
419
+
418
420
if (!isa<Instruction>(V))
419
421
return true ;
420
422
421
- if (GenerateSignBits (V))
422
- return false ;
423
+ if (!isa<OverflowingBinaryOperator> (V))
424
+ return true ;
423
425
424
- return !isa<OverflowingBinaryOperator >(V);
426
+ return cast<Instruction >(V)-> hasNoUnsignedWrap ( );
425
427
}
426
428
427
429
// / Return the intrinsic for the instruction that can perform the same
@@ -469,61 +471,34 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
469
471
InstsToRemove.insert (I);
470
472
}
471
473
472
- void IRPromoter::PrepareConstants () {
474
+ void IRPromoter::PrepareWrappingAdds () {
475
+ LLVM_DEBUG (dbgs () << " ARM CGP: Prepare underflowing adds.\n " );
473
476
IRBuilder<> Builder{Ctx};
474
- // First step is to prepare the instructions for mutation. Most constants
475
- // just need to be zero extended into their new type, but complications arise
476
- // because:
477
- // - For nuw binary operators, negative immediates would need sign extending;
478
- // however, instead we'll change them to positive and zext them. We can do
479
- // this because:
480
- // > The operators that can wrap are: add, sub, mul and shl.
481
- // > shl interprets its second operand as unsigned and if the first operand
482
- // is an immediate, it will need zext to be nuw.
483
- // > I'm assuming mul has to interpret immediates as unsigned for nuw.
484
- // > Which leaves the nuw add and sub to be handled; as with shl, if an
485
- // immediate is used as operand 0, it will need zext to be nuw.
486
- // - We also allow add and sub to safely overflow in certain circumstances
487
- // and only when the value (operand 0) is being decreased.
488
- //
489
- // For adds and subs, that are either nuw or safely wrap and use a negative
490
- // immediate as operand 1, we create an equivalent instruction using a
491
- // positive immediate. That positive immediate can then be zext along with
492
- // all the other immediates later.
493
- for (auto *V : *Visited) {
494
- if (!isa<Instruction>(V))
495
- continue ;
496
477
497
- auto *I = cast<Instruction>(V);
498
- if (SafeToPromote->count (I)) {
499
-
500
- if (!isa<OverflowingBinaryOperator>(I))
501
- continue ;
502
-
503
- if (auto *Const = dyn_cast<ConstantInt>(I->getOperand (1 ))) {
504
- if (!Const->isNegative ())
505
- continue ;
478
+ // For adds that safely wrap and use a negative immediate as operand 1, we
479
+ // create an equivalent instruction using a positive immediate.
480
+ // That positive immediate can then be zext along with all the other
481
+ // immediates later.
482
+ for (auto *I : *SafeWrap) {
483
+ if (I->getOpcode () != Instruction::Add)
484
+ continue ;
506
485
507
- unsigned Opc = I->getOpcode ();
508
- if (Opc != Instruction::Add && Opc != Instruction::Sub)
509
- continue ;
486
+ LLVM_DEBUG (dbgs () << " ARM CGP: Adjusting " << *I << " \n " );
487
+ assert ((isa<ConstantInt>(I->getOperand (1 )) &&
488
+ cast<ConstantInt>(I->getOperand (1 ))->isNegative ()) &&
489
+ " Wrapping should have a negative immediate as the second operand" );
510
490
511
- LLVM_DEBUG (dbgs () << " ARM CGP: Adjusting " << *I << " \n " );
512
- auto *NewConst = ConstantInt::get (Ctx, Const->getValue ().abs ());
513
- Builder.SetInsertPoint (I);
514
- Value *NewVal = Opc == Instruction::Sub ?
515
- Builder.CreateAdd (I->getOperand (0 ), NewConst) :
516
- Builder.CreateSub (I->getOperand (0 ), NewConst);
517
- LLVM_DEBUG (dbgs () << " ARM CGP: New equivalent: " << *NewVal << " \n " );
518
-
519
- if (auto *NewInst = dyn_cast<Instruction>(NewVal)) {
520
- NewInst->copyIRFlags (I);
521
- NewInsts.insert (NewInst);
522
- }
523
- InstsToRemove.insert (I);
524
- I->replaceAllUsesWith (NewVal);
525
- }
491
+ auto Const = cast<ConstantInt>(I->getOperand (1 ));
492
+ auto *NewConst = ConstantInt::get (Ctx, Const->getValue ().abs ());
493
+ Builder.SetInsertPoint (I);
494
+ Value *NewVal = Builder.CreateSub (I->getOperand (0 ), NewConst);
495
+ if (auto *NewInst = dyn_cast<Instruction>(NewVal)) {
496
+ NewInst->copyIRFlags (I);
497
+ NewInsts.insert (NewInst);
526
498
}
499
+ InstsToRemove.insert (I);
500
+ I->replaceAllUsesWith (NewVal);
501
+ LLVM_DEBUG (dbgs () << " ARM CGP: New equivalent: " << *NewVal << " \n " );
527
502
}
528
503
for (auto *I : NewInsts)
529
504
Visited->insert (I);
@@ -731,6 +706,8 @@ void IRPromoter::Cleanup() {
731
706
NewInsts.clear ();
732
707
TruncTysMap.clear ();
733
708
Promoted.clear ();
709
+ SafeToPromote->clear ();
710
+ SafeWrap->clear ();
734
711
}
735
712
736
713
void IRPromoter::ConvertTruncs () {
@@ -762,7 +739,8 @@ void IRPromoter::Mutate(Type *OrigTy,
762
739
SetVector<Value*> &Visited,
763
740
SmallPtrSetImpl<Value*> &Sources,
764
741
SmallPtrSetImpl<Instruction*> &Sinks,
765
- SmallPtrSetImpl<Instruction*> &SafeToPromote) {
742
+ SmallPtrSetImpl<Instruction*> &SafeToPromote,
743
+ SmallPtrSetImpl<Instruction*> &SafeWrap) {
766
744
LLVM_DEBUG (dbgs () << " ARM CGP: Promoting use-def chains to from "
767
745
<< ARMCodeGenPrepare::TypeSize << " to 32-bits\n " );
768
746
@@ -775,6 +753,7 @@ void IRPromoter::Mutate(Type *OrigTy,
775
753
this ->Sources = &Sources;
776
754
this ->Sinks = &Sinks;
777
755
this ->SafeToPromote = &SafeToPromote;
756
+ this ->SafeWrap = &SafeWrap;
778
757
779
758
// Cache original types of the values that will likely need truncating
780
759
for (auto *I : Sinks) {
@@ -797,9 +776,9 @@ void IRPromoter::Mutate(Type *OrigTy,
797
776
TruncTysMap[Trunc].push_back (Trunc->getDestTy ());
798
777
}
799
778
800
- // Convert adds and subs using negative immediates to equivalent instructions
801
- // that use positive constants.
802
- PrepareConstants ();
779
+ // Convert adds using negative immediates to equivalent instructions that use
780
+ // positive constants.
781
+ PrepareWrappingAdds ();
803
782
804
783
// Insert zext instructions between sources and their users.
805
784
ExtendSources ();
@@ -889,7 +868,7 @@ bool ARMCodeGenPrepare::isLegalToPromote(Value *V) {
889
868
if (SafeToPromote.count (I))
890
869
return true ;
891
870
892
- if (isPromotedResultSafe (V) || isSafeOverflow (I)) {
871
+ if (isPromotedResultSafe (V) || isSafeWrap (I)) {
893
872
SafeToPromote.insert (I);
894
873
return true ;
895
874
}
@@ -1025,7 +1004,8 @@ bool ARMCodeGenPrepare::TryToPromote(Value *V) {
1025
1004
if (ToPromote < 2 )
1026
1005
return false ;
1027
1006
1028
- Promoter->Mutate (OrigTy, CurrentVisited, Sources, Sinks, SafeToPromote);
1007
+ Promoter->Mutate (OrigTy, CurrentVisited, Sources, Sinks, SafeToPromote,
1008
+ SafeWrap);
1029
1009
return true ;
1030
1010
}
1031
1011
0 commit comments